# -*- coding: utf-8 -*-
# __authon__: YB.dalon
import socket
import httplib
import urllib
import json
import socket
import ssl
import ConfigParser
import os, sys, shutil
from ylogger import logger

def convert_dict2urlcode(dictdata):
    try:
        # 数据判断必须是一个json类型，先使用json.load加载出来，然后用eval去将cf读取来的字符串转为字典
        # json.loads()将字符串转换成字典，使用urlencode加载的时候，有中文编码问题，不知道如何解决，先这么处理
        try:
            data1 = json.loads(dictdata)
        except:
            return
        data1 = eval(dictdata)
        params = urllib.urlencode(data1)
        return params
    except:
        return

def http_get(cf, log):
    header, data = _build_http_header(cf)
    targetip = cf.get('basic_conf', 'targetip')
    port = cf.getint('basic_conf', 'targetport')
    if data:
        params = convert_dict2urlcode(data)
        if params:
            uri = cf.get('http_conf', 'uri') + '?' + params
        else:
            log.log_warn('data format must be {"name":"alex","passwd":"123"}   attention: double quotation marks ')
            return
    else:
        uri = cf.get('http_conf', 'uri')
    try:
        if cf.get('http_conf', 'https_mode').lower() == 'on':
            conn = httplib.HTTPSConnection(targetip)
            sock = socket.create_connection((targetip, port), cf.getint('other_config', 'timeout'))
            conn.sock = ssl.wrap_socket(sock, conn.key_file, conn.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)
        else:
            conn = httplib.HTTPConnection(targetip, port, timeout=cf.getint('other_config', 'timeout'))
        log.log_critical('>>>get url: http://%s:%s%s ... ...\n' % (targetip, port, uri))
        conn.request("GET", uri, headers = header)
        log.log_critical('>>>send http_header:\n%s\n' % header)
        response = conn.getresponse()
        log.log_critical('http response: %s %s'%(response.status, response.reason))
        log.log_all('\r\n'.join([':'.join([i[0], i[1]])for i in response.getheaders()]))
        rdata = response.read()
        log.log_all(rdata)
        conn.close()
    except:
        log.log_warn('there is something wrong when client connnects to  %s  and recive data'%targetip)
        return

def http_post(cf, log):
    header, data = _build_http_header(cf)
    targetip = cf.get('basic_conf', 'targetip')
    port = cf.getint('basic_conf', 'targetport')
    if not data:
        log.log_warn('request method is POST but data is none!')
    else:
        try:
            #支持两种数据类型上传： 普通文本和json
            if cf.get('body_data', 'data_type') == 'json':
                #如果数据类型是json，则需要加Content-Type: application/json;charset=utf-8
                header['Content-Type'] = 'application/json;charset=utf-8'
                body_data = data
            elif cf.get('body_data', 'data_type') == 'urlcode':
                header['Content-Type'] = 'application/x-www-form-urlencoded'
                try:
                    body_data = convert_dict2urlcode(data)
                except:
                    log.log_warn('data format must be {"name":"alex","passwd":"123"}   attention: double quotation marks ')
                    return
            else:
                # 数据为text类型，post数据
                # 需要添加头部：Content-Type: text/html; charset=UTF-8
                header['Content-Type'] = 'text/html; charset=UTF-8'
                body_data = data
            header['Content-Length'] = str(len(body_data))
        except:
            log.log_warn('data format must be {"name":"alex","passwd":"123"} ')
            return
    try:
        if cf.get('http_conf', 'https_mode').lower() == 'on':
            conn = httplib.HTTPSConnection(targetip)
            sock = socket.create_connection((targetip, port), cf.getint('other_config', 'timeout'))
            conn.sock = ssl.wrap_socket(sock, conn.key_file, conn.cert_file, ssl_version=ssl.PROTOCOL_TLSv1)
        else:
            conn = httplib.HTTPConnection(targetip, port, timeout=cf.getint('other_config', 'timeout'))
        conn.request("POST", cf.get('http_conf', 'uri'), body_data, headers=header)
        log.log_critical('>>>send http_header:\n%s\n' % header)
        log.log_critical('>>>send http_content:\n%s\n' % body_data)
        response = conn.getresponse()
        log.log_critical('http response: %s %s' % (response.status, response.reason))
        log.log_all('\r\n'.join([':'.join([i[0], i[1]]) for i in response.getheaders()]))
        rdata = response.read()
        log.log_all(rdata)
        conn.close()
    except:
        log.log_warn('there is something wrong when client connnects to  %s  and recive data' % targetip)
        return
def _build_http_header(cf):
    header = {}
    if cf.getint('basic_conf', 'targetport')==80:
        header['Host'] = cf.get('basic_conf', 'targetip')
    else:
        header['Host'] = '%s:%s'%(cf.get('basic_conf', 'targetip'),
                                  cf.get('basic_conf', 'targetport'))
    data = cf.get('body_data', 'data')
    if data and cf.get('http_conf', 'method').upper() == 'POST':
        header['Content-Length'] = str(len(data))
    #先不处理mimeType
    for h in cf.options('http_header'):
        header['-'.join([i.capitalize() for i in h.split('-')])] = cf.get('http_header', h)
    return header, data
def config_read():
    if not os.path.exists('config.ini'):
        shutil.copyfile('default_config.ini', 'config.ini')
    conf = ConfigParser.ConfigParser()
    conf.read('config.ini')
    return conf
def config_write():
    pass
def main():
    cf = config_read()
    loglevel = cf.get('other_config', 'loglevel')
    log = logger('runlog.log', loglevel)
    if cf.get('http_conf', 'method').upper() == 'GET':
        http_get(cf, log)
    elif cf.get('http_conf', 'method').upper() == 'POST':
        http_post(cf, log)
    else:
        log.log_warn('only support GET and POST')
        return
    log.exit()
def test():
    pass

if __name__ == '__main__':
    main()